package com.zdp.contentcenter.service.content;

import com.zdp.contentcenter.dao.content.RocketmqTransactionLogMapper;
import com.zdp.contentcenter.dao.content.ShareMapper;
import com.zdp.contentcenter.domain.dto.content.ShareAuditDTO;
import com.zdp.contentcenter.domain.dto.content.ShareDTO;
import com.zdp.contentcenter.domain.dto.message.UserAddBonusMsgDTO;
import com.zdp.contentcenter.domain.dto.user.UserDTO;
import com.zdp.contentcenter.domain.entity.content.RocketmqTransactionLog;
import com.zdp.contentcenter.domain.entity.content.Share;
import com.zdp.contentcenter.domain.enums.AuditStatusEnum;
import com.zdp.contentcenter.feignclient.UserCenterFeignClient;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
import java.util.UUID;


/**
 * @author sesshomaru
 * @date 2020/9/17 0:18
 */
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
@Service
public class ShareService {

    private final ShareMapper shareMapper;

    private final UserCenterFeignClient userCenterFeignClient;

    private final RocketMQTemplate rocketMQTemplate;

    private final RocketmqTransactionLogMapper rocketmqTransactionLogMapper;

    public ShareDTO findById(Integer id) {
        // 获取分享详情
        Share share = this.shareMapper.selectByPrimaryKey(id);
        // 发布人id
        Integer userId = share.getUserId();

        UserDTO userDTO = userCenterFeignClient.findById(userId);

        ShareDTO shareDTO = new ShareDTO();
        BeanUtils.copyProperties(share, shareDTO);
        shareDTO.setWxNickName(userDTO.getWxNickname());

        return shareDTO;
    }


    public Share auditById(Integer id, ShareAuditDTO shareAuditDTO) {
        // 1.查询share是否存在, 不存在或者当前的审核状态不是待审核 则抛出异常
        Share share = this.shareMapper.selectByPrimaryKey(id);
        if (share == null) {
            throw new IllegalArgumentException("参数非法! 该分享不存在!");
        }
        if (!Objects.equals("NOT_YET", share.getAuditStatus())) {
            throw new IllegalArgumentException("参数非法! 该分享已审核通过或者审核不通过");
        }

        // 如审核状态是PASS那么就发送事务消息给用户添加积分
        if (AuditStatusEnum.PASS.equals(shareAuditDTO.getAuditStatusEnum())) {
            // 发送半消息到rocket
            String transactionId = UUID.randomUUID().toString().trim();
            this.rocketMQTemplate.sendMessageInTransaction(
                    // 这个事务生产者组参数随便取
                    "tx-add-bonus-group",
                    "add-bonus",
                    MessageBuilder.withPayload(UserAddBonusMsgDTO.builder()
                            .userId(share.getUserId())
                            .bonus(50)
                            .build()
                    )
                            // header也有大用处
                            .setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
                            .setHeader("share_id", id)
                            .build(),
                    // arg有大用处
                    shareAuditDTO);
        } else {
            // 如果审核不是PASS的话就单纯的修改分享状态即可(只做单纯的数据库修改即可)
            this.auditByIdInDB(id, shareAuditDTO);
        }
        return share;
    }

    public void auditByIdInDB(Integer id, ShareAuditDTO auditDTO){
        // 审核分享 修改分享状态
        Share share = Share.builder()
                .id(id)
                .auditStatus(auditDTO.getAuditStatusEnum().toString())
                .reason(auditDTO.getReason()).build();
        // 注意这里一定要使用updateByPrimaryKeySelective
        this.shareMapper.updateByPrimaryKeySelective(share);
        //todo 把更新后的share写入缓存
    }

    @Transactional(rollbackFor = Exception.class)
    public void auditByIdWithRocketMqLog(Integer id, ShareAuditDTO auditDTO, String transactionId){
        // 执行一下单纯的本地事务方法(修改审核状态)
        this.auditByIdInDB(id, auditDTO);
        // 记录日志
        rocketmqTransactionLogMapper.insertSelective(
                RocketmqTransactionLog.builder()
                .transactionId(transactionId)
                .log("审核分享....")
                .build()
        );
    }

}
